﻿unit GlobalMonitor;

interface

uses
  Winapi.Windows, System.SysUtils;

type

  TGlobalMonitor = class
  public
    m_bStart:           Boolean;                (* 是否开始监视           *)
    m_nTotalRecvBytes:  Int64;                  (* 总接受字节             *)
    m_nTotalSendBytes:  Int64;                  (* 总发送字节             *)
    m_nTotalRecvKB:     Int64;                  (* 总接受KB               *)
    m_nTotalSendKB:     Int64;                  (* 总发送KB               *)
    m_nTotalRecvMB:     Int64;                  (* 总接受MB               *)
    m_nTotalSendMB:     Int64;                  (* 总发送MB               *)
    m_nTotalRecvGB:     Int64;                  (* 总接受GB               *)
    m_nTotalSendGB:     Int64;                  (* 总发送GB               *)
    m_nTotalRecvTB:     Int64;                  (* 总接受TB               *)
    m_nTotalSendTB:     Int64;                  (* 总发送TB               *)
    m_nDayRun:          Int64;                  (* 运行天                 *)
    m_nHourRun:         Int64;                  (* 运行时                 *)
    m_nMinuteRun:       Int64;                  (* 运行分                 *)
    m_nSecondRun:       Int64;                  (* 运行秒                 *)

    m_iocpRecvCount:    Int64;                  (* IOCP队列中Recv数       *)
    m_iocpSendCount:    Int64;                  (* IOCP队列中Send数       *)
    m_RecvCount:        Int64;                  (* Recv投递数量           *)
    m_SendCount:        Int64;                  (* Send投递数量           *)
    m_SendRate:         Real;                   (* 发送每秒字节流量       *)
    m_RecvRate:         Real;                   (* 接受每秒字节流量       *)

    m_iNewBufferCount:  Int64;                  (* 申请Buffer次数         *)
    m_iFreeBufferCount: Int64;                  (* 释放Buffer次数         *)
    m_MaxHistoryCount:  Cardinal;                  (* 最大连接数             *)
    m_MaxHistoryTime:   String;                 (* 最大连接数峰值时间     *)
    m_LockGlobalCount:  Integer;                (* 全局锁计数             *)

    m_StartRun:         Cardinal;                  (* 起始时间 (上一次)      *)
    m_LastRun:          Cardinal;                  (* 终止时间 (最后一次)    *)

  public
    procedure ClearMonitor;                     (* 清空                   *)
    procedure StartMonitor;                     (* 开始                   *)
    procedure StopMonitor;                      (* 停止                   *)
    procedure CalcCapability;                   (* 计算性能               *)

    procedure ProcIOCPPostRecv;                 (* 处理Post Recv I/O      *)
    procedure PortIOCPOnRecv(nRecvByte: Cardinal); (* 增加接受字节数         *)
    procedure ProcIOCPPostSend;                 (* 处理Post Send I/O      *)
    procedure PortIOCPOnSend(nSendByte: Cardinal); (* 增加发送字节数         *)

    procedure AddNewBuffer;                     (* IOCP物理分配Buffer次数 *)
    procedure AddFreeBuffer;                    (* IOCP物理释放Buffer次数 *)
                                                (* 处理历史峰值           *)
    procedure ProcSocketConnCount(iMaxConn: Cardinal);

  public
    constructor Create;
    destructor Destroy; override;
  end;

var
  _GlobalMonitor: TGlobalMonitor;

implementation

constructor TGlobalMonitor.Create;
begin
  inherited Create;
  ClearMonitor;
end;

destructor TGlobalMonitor.Destroy;
begin
  inherited Destroy;
end;

procedure TGlobalMonitor.ClearMonitor;
begin
  m_nTotalRecvBytes := 0;     (* 总接受字节           *)
  m_nTotalSendBytes := 0;     (* 总发送字节           *)
  m_nTotalRecvKB := 0;        (* 总接受KB             *)
  m_nTotalSendKB := 0;        (* 总发送KB             *)
  m_nTotalRecvMB := 0;        (* 总接受MB             *)
  m_nTotalSendMB := 0;        (* 总发送MB             *)
  m_nTotalRecvGB := 0;        (* 总接受GB             *)
  m_nTotalSendGB := 0;        (* 总接受GB             *)
  m_nTotalRecvTB := 0;        (* 总接受TB             *)
  m_nTotalSendTB := 0;        (* 总接受TB             *)

  m_nDayRun := 0;             (* 运行天               *)
  m_nHourRun := 0;            (* 运行时               *)
  m_nMinuteRun := 0;          (* 运行分               *)
  m_nSecondRun := 0;          (* 运行秒               *)
  m_StartRun := 0;            (* 起始时间 (上一次)    *)
  m_LastRun := 0;             (* 终止时间 (最后一次)  *)
  m_MaxHistoryCount := 0;     (* 历史最大上限         *)
  m_MaxHistoryTime := FormatDateTime('YYYY-MM-DD HH:MM:SS', Now());
  m_RecvCount := 0;           (* Recv投递数           *)
  m_SendCount := 0;           (* Send投递数           *)
  m_iocpRecvCount := 0;       (* IOCP队列中Recv数     *)
  m_iocpSendCount := 0;       (* IOCP队列中Send数     *)

  m_iNewBufferCount := 0;     (* 申请Buffer次数       *)
  m_iFreeBufferCount := 0;    (* 释放Buffer次数       *)
  m_LockGlobalCount := 0;     (* 全局锁清零           *)
end;

procedure TGlobalMonitor.StartMonitor;
begin
  if not m_bStart then begin
    ClearMonitor;
    m_bStart := TRUE;
    m_StartRun := GetTickCount;
  end;
end;

procedure TGlobalMonitor.StopMonitor;
begin
  if m_bStart then begin
    ClearMonitor;
    m_bStart := FALSE;
  end;
end;

procedure TGlobalMonitor.ProcSocketConnCount(iMaxConn: Cardinal);
begin
  if m_bStart then begin
    if iMaxConn > m_MaxHistoryCount then begin
      m_MaxHistoryCount := iMaxConn;
      m_MaxHistoryTime := FormatDateTime('YYYY-MM-DD HH:MM:SS', Now());
    end;
  end;
end;

procedure TGlobalMonitor.CalcCapability;
var
  m_CountSec: Integer;
  m_RecvByte: Real;
  m_SendByte: Real;
begin
  if m_bStart then
  begin

    m_LastRun := GetTickCount;

    (* 得到秒                            *)
    m_nSecondRun := m_nSecondRun + (m_LastRun - m_StartRun) div 1000;
    (* 修改起始时间   (最后时间-余数)    *)
    m_StartRun := m_LastRun - (m_LastRun - m_StartRun) mod 1000;
    (* 秒转成分                          *)
    m_nMinuteRun := m_nMinuteRun + m_nSecondRun div 60;
    m_nSecondRun :=  m_nSecondRun mod 60;
    (* 分转成时                          *)
    m_nHourRun := m_nHourRun + m_nMinuteRun div 60;
    m_nMinuteRun :=  m_nMinuteRun mod 60;
    (* 时转换成天                        *)
    m_nDayRun := m_nDayRun + m_nHourRun div 24;
    m_nHourRun := m_nHourRun mod 24;


    (* 字节转化成KB                      *)
    m_nTotalRecvKB := m_nTotalRecvKB + m_nTotalRecvBytes div 1024;
    m_nTotalSendKB := m_nTotalSendKB + m_nTotalSendBytes div 1024;
    m_nTotalRecvBytes := m_nTotalRecvBytes mod 1024;
    m_nTotalSendBytes := m_nTotalSendBytes mod 1024;
    (* KB转化成MB                        *)
    m_nTotalRecvMB := m_nTotalRecvMB + m_nTotalRecvKB div 1024;
    m_nTotalSendMB := m_nTotalSendMB + m_nTotalSendKB div 1024;
    m_nTotalRecvKB := m_nTotalRecvKB mod 1024;
    m_nTotalSendKB := m_nTotalSendKB mod 1024;
    (* MB转化成GB                        *)
    m_nTotalRecvGB := m_nTotalRecvGB + m_nTotalRecvMB div 1024;
    m_nTotalSendGB := m_nTotalSendGB + m_nTotalSendMB div 1024;
    m_nTotalRecvMB := m_nTotalRecvMB mod 1024;
    m_nTotalSendMB := m_nTotalSendMB mod 1024;
    (* GB转化成TB                        *)
    m_nTotalRecvTB := m_nTotalRecvTB + m_nTotalRecvGB div 1024;
    m_nTotalSendTB := m_nTotalSendTB + m_nTotalSendGB div 1024;
    m_nTotalRecvGB := m_nTotalRecvGB mod 1024;
    m_nTotalSendGB := m_nTotalSendGB mod 1024;


    (* 计算RECV流量 秒                   *)
    m_CountSec := m_nDayRun * 24*60*60+
                  m_nHourRun * 60*60+
                  m_nMinuteRun*60+
                  m_nSecondRun;
    m_RecvByte := m_nTotalRecvTB*1024*1024*1024*1024 +
                  m_nTotalRecvGB*1024*1024*1024 +
                  m_nTotalRecvMB*1024*1024+
                  m_nTotalRecvKB*1024+
                  m_nTotalRecvBytes;

    (* 每秒字节流量                      *)
    if m_CountSec<>0 then m_RecvRate := m_RecvByte/m_CountSec
    else
      m_RecvRate := 0;

    m_SendByte := m_nTotalSendTB*1024*1024*1024*1024 +
                  m_nTotalSendGB*1024*1024*1024 +
                  m_nTotalSendMB*1024*1024+
                  m_nTotalSendKB*1024+
                  m_nTotalSendBytes;

    if m_CountSec<>0 then m_SendRate := m_SendByte/m_CountSec
    else
      m_SendRate := 0;
  end;
end;

procedure TGlobalMonitor.ProcIOCPPostRecv;
begin
  m_iocpRecvCount := m_iocpRecvCount + 1;
  m_RecvCount := m_RecvCount + 1;
end;

procedure TGlobalMonitor.PortIOCPOnRecv(nRecvByte: Cardinal);
begin
  if m_iocpRecvCount>0 then
    m_iocpRecvCount := m_iocpRecvCount - 1;
  m_nTotalRecvBytes := m_nTotalRecvBytes + nRecvByte;
end;

procedure TGlobalMonitor.ProcIOCPPostSend;
begin
  m_iocpSendCount := m_iocpSendCount + 1;
  m_SendCount := m_SendCount + 1;
end;

procedure TGlobalMonitor.PortIOCPOnSend(nSendByte: Cardinal); (* 增加发送字节数         *)
begin
  if m_iocpSendCount>0 then
    m_iocpSendCount := m_iocpSendCount - 1;
  m_nTotalSendBytes := m_nTotalSendBytes + nSendByte;
end;

procedure TGlobalMonitor.AddNewBuffer;
begin
  m_iNewBufferCount := m_iNewBufferCount + 1;
end;

procedure TGlobalMonitor.AddFreeBuffer;
begin
  m_iFreeBufferCount := m_iFreeBufferCount + 1;
end;

initialization
  _GlobalMonitor := TGlobalMonitor.Create;

finalization
  FreeAndNil(_GlobalMonitor);

end.
